/**
 * @file button_monitor.h
 * @author monster
 * @brief 
 * @version 0.1
 * @date 2024-04-28
 * 
 * @copyright Copyright (c) 2024
 * 
 */
#ifndef __BUTTON_MONITOR_H
#define __BUTTON_MONITOR_H

/*********************
 *      INCLUDES
 *********************/
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {



#endif // __cplusplus


/*********************
 *      DEFINES
 *********************/

/* Enable dynamic memory create button */
#define BM_DYNAMIC_MEMORY   0

/* Button object max number */
#if !BM_DYNAMIC_MEMORY
#define BM_BUTTON_SIZE      10
#endif


/**********************
 *      TYPEDEFS
 **********************/

/* Button Event type */
typedef enum {
	EVENT_NONE,
	EVENT_PRESSED,
	EVENT_PRESSING,
	EVENT_LONG_PRESSED,
	EVENT_LONG_PRESSED_REPEAT,
	EVENT_LONG_PRESSED_RELEASED,
	EVENT_RELEASED,
	EVENT_CHANGED,
	EVENT_CLICKED,
	EVENT_SHORT_CLICKED,
	EVENT_DOUBLE_CLICKED,
	EVENT_LAST
} button_event_t;

/* Button state type */
typedef enum {
	STATE_NO_PRESS,
	STATE_PRESS,
	STATE_LONG_PRESS
} button_state_t;

/* Button trigger record */
typedef struct {
	uint8_t  pressed      : 1;
	uint8_t  clicked      : 1;
	uint8_t  shortClicked : 1;
	uint8_t  longPressed  : 1;
	uint16_t clickCnt;
} button_record_t;


struct _button_t;

/* Button callback function typedef */
typedef void (*button_callback_t)(struct _button_t* btn, int event);

/* Get Button press function typedef */
typedef bool (*button_press_t)(char* name);

/* Get tick function typedef */
typedef uint32_t (*get_tick_t)(void);


/* Button object description */
typedef struct _button_t {
	char*           name;     //!< Button name
	button_state_t  nowState; //!< Current state
	button_record_t record;   //!< Button record

	button_callback_t callback;  //!< Button event callback pointer
	button_press_t    get_press; //!< Get button press status function pointer

	struct {
		uint16_t longPressTimeCfg;
		uint16_t longPressRepeatTimeCfg;
		uint16_t doubleClickTimeCfg;
		uint32_t lastLongPressTime;
		uint32_t lastPressTime;
		uint32_t lastClickTime;
		uint8_t  isLongPressed : 1;
	} priv; //!< Button config params

	struct _button_t* next; //!< Next button node
} button_t;


/**********************
 * GLOBAL PROTOTYPES
 **********************/

/**
 * @brief Set get tick function callback
 * @param tick Pointer to get_tick_t
 */
void button_set_tick(get_tick_t tick);

/**
 * @brief Create a new button
 *
 * @param name  this button name
 * @param get_press button press function pointer
 * @param callback  button event callback pointer
 * @param long_press_time
 * @param long_press_time_repeat
 * @param double_click_time
 * @return pointer to the new button
 */
button_t* button_create(char*    name, button_press_t      get_press, button_callback_t     callback,
						uint16_t long_press_time, uint16_t long_press_time_repeat, uint16_t double_click_time);

/**
 * @brief Remove button
 * @param btn to a button_t pointer
 */
void button_remove(button_t* btn);

/**
 * @brief Get button press record
 * @param btn to a button_t pointer
 * @return If button is exist return record, else return NULL.
 */
button_record_t button_get_record(button_t* btn);

/**
 * @brief Monitor once button
 * @param btn to a button_t pointer
 */
void button_monitor(button_t* btn);

/**
 * @brief handler all button event
 * @return None
 */
void button_handler(void);

#ifdef __cplusplus
} // extern "C" {
#endif // __cplusplus

#endif // __BUTTON_MONITOR_H
